#!/usr/bin/perl

use Fcntl;
use POSIX;

my $maudepath = "/home/software/maude22/maude.linux";
$ENV{MAUDE_LIB} = "/home/software/maude22";
my $pgmfile = "/home/software/mopplugins/ERE/min5.maude";

my $ere_orig ;
my $res = "";

my $filename;
my $dot_input;
my $html_output;
my $maude_input;

create_maude_input();
exec_maude();
create_output();
print $html_output."\n";

sub create_maude_input {
    my $elt;
    my $ops = "";
    my $eset = "  eq eset = ";
    while (<>) {
	    if (/^\s*[Ee]vent\s+([^\t <]+)[^:]*:/) {
	    	$elt = $1;
                $ops = $ops."  op $elt : -> Event .\n";
                $eset = $eset." $elt \#";
	    }
		#hack so that we don't have to have :
		#but still can have : for input from the main
		#JavaMOP trial where we don't want to have to strip
		#off the pointcuts 
		elsif (/^\s*[Ee]vent\s+([^\t <]+)/) {
	    	$elt = $1;
                $ops = $ops."  op $elt : -> Event .\n";
                $eset = $eset." $elt \#";
	    }
	    elsif (/^\s*[Ee]re\s*:\s*(.*)/) {
		    $ere_orig = $1;
	    }
    }
    chop $eset ;
    $eset = $eset." .\n";
    $ere_orig =~ s/[\n]/ /g;
    #join(' ',split(/$/, $ere_orig));
    my $ere = $ere_orig;
    $ere =~ s/empty/\$/g ;
    $ere =~ s/epsilon/\!/g ;
    $ere = join ' ', split /(\w+|[\!\$\~\+\&\*\(\)])/,  $ere;
    $ere =~ s/\$/empty/g;
    $ere =~ s/\!/epsilon/g;
    $ere =~ s/;//g;

    $maude_input = "in $pgmfile\n";
    $maude_input = $maude_input.$ops.$eset."endfm\n";
    $maude_input = $maude_input."red build($ere) .\n";
    $maude_input = $maude_input."quit .\n";
}

sub exec_maude{

    my $i = 0;
    while (-e "/tmp/dfa.out$i") {
        $i++;
    }

    open MAUDEIN, "|$maudepath > /tmp/dfa.out$i" || die "Cannot execute $maudepath\n";
    print MAUDEIN $maude_input;
    close MAUDEIN;

    open MAUDEOUT, "</tmp/dfa.out$i" || die "Cannot open /tmp/dfa.out$i\n";
    my $flag = 0;
    my $line;
    while($line = <MAUDEOUT>){
        chomp($line);
        if($line =~ /^result Automata: (.*)$/){
            $res = $1;
            $flag = 1;
        }
        else {
            if($line =~ /^Bye/) {
                $flag = 0;
            }
            if($flag) {
                $res = $res.$line;
            }}
    }
    close(MAUDEOUT);
    system("rm -f /tmp/dfa.out$i");
}

sub create_output{
    $res =~ /^\{(.*)\}$/;
    $res = $1;

    my $edges = "";
    my $fsm_output = "";
	#I am not a perl programmer.  I'm sure there is a better way
	#to do this, but as far as I can tell perl doesn't have extensible
	#lists, so I am using a table as a list
	my %states;
	my %edge_table;


    while($res =~ /\[\s*(\w+)\s*,\s*(\w+)\s*\]\W+(\w+)(.*)/){
        my $s1 = "s$1";
		my $s2 = "$2";
		my $s3 = "s$3";
		$edges = $edges . "\t$s1 -> $s3 [ label = \"$s2\" ];\n";
		$edge_table{$s1} .= "    $s2 -> $s3\n";
		$states{$s1} = "def";
		$states{$s3} = "def";
	    $res = $4;
    }


    my $empty = 0;
    my $nodes;
	my $final_states_str;
	#again this is essentialy a list
	#we need to keep track of which states are final states so that we
	#can mark them as such in the fsm output
	my %final_states;
    if($res =~ /nilstate/) {
        $empty = 1;
    }
    else {
        $res =~ /\s*,\s*([^,]+)/;
        $final_states_str = "$1";
        while($final_states_str =~ /([0-9])+(.*)/){
            $nodes .= " s$1";
			$final_states{"s$1"} = 'def';
			$final_states_str = $2;
		}
	}
    
	$txt_output = "fsm:\n";
	#the keys are randomly sorted, we need to make sure that state s0
	#is listed first.  The order of the others does not matter
	if($final_states{'s0'} eq 'def'){
	   $txt_output .= "  !s0[\n".$edge_table{'s0'}."  ]\n";	
	}
	else {
	   $txt_output .= "  s0[\n".$edge_table{'s0'}."  ]\n";	
	}
	foreach(keys %states){
      if($_ eq 's0'){
        next;
	  }
	  if($final_states{$_} eq 'def'){
	    $txt_output .= "  !".$_."[\n".$edge_table{$_}."  ]\n";	
	  }
	  else {
	    $txt_output .= "  ".$_."[\n".$edge_table{$_}."  ]\n";	
	  }
	}

    $dot_input = 'digraph finite_state_machine {'."\n";
    $dot_input = $dot_input."\t rankdir=LR;\n";
    $dot_input = $dot_input."\t".'size="8,8"'."\n";
    if(! $empty) {
       $dot_input = $dot_input."\t".'node [shape = doublecircle];'."\n\t$nodes;\n";
    }
    $dot_input = $dot_input."\t node [shape = circle];\n";
    $dot_input = $dot_input."\t y [shape = plaintext label=\"";
    $dot_input = $dot_input.$ere_orig;
    $dot_input = $dot_input."\"];\n";
    $dot_input = $dot_input."\t x [shape = circle style=invis];\n";
    $dot_input = $dot_input."\t x -> s0 [style=bold]\n";
    $dot_input = $dot_input.$edges."}\n";

    my $i = 0;
	#this is a race condition!  I really don't care, however
	while (-e "/www/www-root/dot_img/ere$i.txt") {
        $i++;
    }
	open (DOT_IN, ">/www/www-root/dot_img/ere$i.txt") || die $!;	
    print DOT_IN $dot_input;

	$env = 'PATH=/home/software/bin:$PATH; export PATH;';
	$env .= 'LD_LIBRARY_PATH="/home/software/graphviz/lib/graphviz"; export LD_LIBRARY_PATH;';
    $command = $env."dot_builtins -Tjpg -o /www/www-root/dot_img/ere$i.jpg /www/www-root/dot_img/ere$i.txt";

    system($command);
	$html_output  = "<form name=\"select_all\">\n";
    $html_output .=  "<textarea name=\"text_area\" rows =\"25\" cols=\"80\">\n";
    $html_output .=  "$txt_output";
  	$html_output .=  "</textarea>\n";
	$html_output .=  "</form>\n";    
    $html_output .= "<img src=\"/dot_img/ere$i.jpg\" /><br />";
    $html_output .= "<INPUT TYPE='button' value='Output Syntax Help'" ;
    $html_output .=
          " onclick='javascript:window.open(\"http://fsl.cs.uiuc.edu/index.php/ERE_Plugin_Output_Syntax\")'>" ;
           
	#$env = 'PATH=/home/software/bin:$PATH; export PATH;';
	#$env .= 'LD_LIBRARY_PATH="/home/software/graphviz/lib/graphviz"; export LD_LIBRARY_PATH;';
	#$command = $env."dot_builtins -Tjpg -o /www/www-root/dot_img/fsm$n.jpg /www/www-root/dot_img/fsm$n.txt";
	# system($command);

}
